
#include <multi_select.h>
#include <sys/select.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//#include <system.h>
#include <common.h>
#include <sys/time.h>
#include <signal.h>

static struct multi_select *multi_select_array[MULTI_SELECT_NUM];

int multi_select_add(struct multi_select *element)
{
	int i;
	for(i=0; i<MULTI_SELECT_NUM; i++) 
	{
		if(multi_select_array[i] == NULL)
		{
			DEBUG("%s i=%d", __FUNCTION__, i);
			multi_select_array[i] = element;
			return 0;
		}
	}

	DEBUG("%s error", __FUNCTION__);
	return -1;
}

int multi_select_remove(struct multi_select *element)
{
	int i;
	for(i=0; i<MULTI_SELECT_NUM; i++) 
	{
		if(multi_select_array[i])
		{
			if(multi_select_array[i] == element) 
			{
				DEBUG("%s i=%d", __FUNCTION__, i);
				multi_select_array[i]->exit(multi_select_array[i]->fd);
				multi_select_array[i]->fd = -1;
				multi_select_array[i] = NULL;
			}
		}
	}

	return 0;
}

int multi_select_loop(void)
{
	int i;
	fd_set fds;
	int maxfd = 0;
	struct timeval timeout;
	
	//thread_sigmask();

	while(1)
	{
		maxfd = 0;
		FD_ZERO(&fds);

		for(i=0; i<MULTI_SELECT_NUM; i++) 
		{
			if(multi_select_array[i])
			{
				if(multi_select_array[i]->fd > 0)
				{
					FD_SET(multi_select_array[i]->fd, &fds);
					if(multi_select_array[i]->fd > maxfd)
					{
						maxfd = multi_select_array[i]->fd;
					}
				} 
				else
				{
					if(multi_select_array[i]->init)
					{
						multi_select_array[i]->fd = multi_select_array[i]->init();
					}
				}
			}
		}

		if(maxfd <= 0)
		{
			sleep(1);
			continue;
		}

		timeout.tv_sec = 1;
		timeout.tv_usec = 0;
		switch(select(maxfd+1, &fds, NULL, NULL, &timeout))
		{
			case -1:
			{
				DEBUG_ERR("multi_select %s", strerror(errno));
			}
			break;
			
			case 0:
			{
				//DEBUG("multi_select timeout"); 
			}
			break;

			default:
			{
				for(i=0; i<MULTI_SELECT_NUM; i++)
				{
					if(multi_select_array[i])
					{
						if(multi_select_array[i]->fd > 0)
						{
							if(FD_ISSET(multi_select_array[i]->fd, &fds))
							{
								if(multi_select_array[i]->recv_data(multi_select_array[i]->fd) < 0)
								{
									multi_select_remove(multi_select_array[i]);
								}
							}
						}
					}
				}
			}
			break;
		}
	}

	return 0;
}

